<?php
///
namespace lxsphp\Core\Mvc;

///
use lxsphp\App;

/**
 * 框架 - HTTP请求信息处理类
 *
 * @version $Id: Request.php 179 2014-07-17 06:14:02Z linsir123 $
 * @package lxsphp\Core\Mvc
 */
class Request
{
	/**
	 * 配置
	 *
	 * @var array
	 */
	public $conf = array();

	/**
	 * 访问相关信息
	 *
	 * @var array
	 */
	public $data = array();

	/**
	 * 请求路由信息
	 *
	 * @var string
	 */
	public $route = '';

	/**
	 * 构造函数
	 */
	public function __construct()
	{
		///
		$this->conf = App::o("app.request");
	}

	/**
	 * 构造一个请求地址
	 *
	 * @param string $route 路由信息
	 * @param array $params 其它参数
	 * @param bool $fullDomain 是否包含完整的域名信息
	 * @param bool $fixRootPath 是否包含完整的相对根路径
	 *
	 * @return string
	 */
	public function createRequest(
		$route = '',
		$params = array(),
		$fullDomain = false,
		$fixRootPath = true)
	{
		///
		$url = $route;
		if ($this->conf['route']['type'] != URL_REWRITE)
			$url = basename($_SERVER['SCRIPT_NAME']) . '/' . $url;

		///
		if (is_array($params)) {
			foreach ($params as $key => $val)
				$url .= '/' . rawurlencode($key) . '/' . rawurlencode($val);
		}

		///
		$rootPath = $fixRootPath ? $this->getRelRootPath() : '/';

		if ($fullDomain) {
			$query = 'http://' . $_SERVER['SERVER_NAME'];
			if ($_SERVER['SERVER_PORT'] != 80)
				$query .= ':' . $_SERVER['SERVER_PORT'];

			$rootPath = $query . $rootPath;
		}

		///
		return $rootPath . $url;
	}

	/**
	 * 取得IP
	 *
	 * @return string
	 */
	public function getIp()
	{
		///
		$key = "IP";

		///
		if (! isset($this->data[$key])) {
			if (getenv('HTTP_CLIENT_IP')
				&& strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')
			)
				$ip = getenv('HTTP_CLIENT_IP');
			elseif (getenv('HTTP_X_FORWARDED_FOR')
				&& strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')
			)
				$ip = getenv('HTTP_X_FORWARDED_FOR');
			elseif (getenv('REMOTE_ADDR')
				&& strcasecmp(getenv('REMOTE_ADDR'), 'unknown')
			)
				$ip = getenv('REMOTE_ADDR');
			elseif (isset($_SERVER['REMOTE_ADDR'])
				&& $_SERVER['REMOTE_ADDR']
				&& strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')
			)
				$ip = $_SERVER['REMOTE_ADDR'];
			else
				$ip = null;

			///
			preg_match("/[\d\.]{7,15}/", $ip, $m);
			$this->data[$key] = $m[0] ? $m[0] : 'unknown';
		}

		///
		return $this->data[$key];
	}

	/**
	 * 取得相对根目录的访问路径
	 *
	 * @return string
	 */
	public function getRelRootPath()
	{
		///
		$key = "REL_ROOT_PATH";

		///
		if (! isset($this->data[$key])) {
			$uri = trim($_SERVER['REQUEST_URI']);
			$script = trim($_SERVER['SCRIPT_NAME']);
			$uri = substr($uri, 0, strrpos($uri, '/'));
			$script = substr($script, 0, strrpos($script, '/'));
			if (empty($script) || strpos($uri, $script) === false)
				$script = '';

			///
			$script = preg_replace("/\/+(api|archiver|wap)?\/*$/i", '', $script) . '/';
			$this->data[$key] = htmlspecialchars($script);
		}

		///
		return $this->data[$key];
	}

	/**
	 * 解析路由
	 *
	 * @return array
	 */
	public function parse()
	{
		/// 1
		$type = $this->conf['route']['type'];
		if ($type == URL_PHPINFO && isset($_SERVER['PATH_INFO']))
			$this->route = substr($_SERVER['PATH_INFO'], 1);

		elseif ($type == URL_REWRITE && isset($_GET['url']))
			$this->route = $_GET['url'];

		/// 2
		return $this->_parseController();
	}

	/**
	 * 解析路由
	 * app/appSub/controller/action
	 *
	 * @return array
	 * @example array(
	 *  array(app, appSub),
	 *  array(controller, action)
	 * )
	 */
	private function _parseController()
	{
		///
		$app = "";
		$appSub = "";
		$data = array();
		$v = explode('/', $this->route);
		$default = $this->conf['controller']['default'];
		$subs = $this->conf['controller']['subs'];

		/**
		 * 检测子项目
		 */
		if (isset($v[0])
			&& is_array($subs)
			&& array_key_exists($v[0], $subs)
		) {
			$app = array_shift($v);
			if (isset($v[0])
				&& is_array($subs[$app])
				&& in_array($v[0], $subs[$app])
			)
				$appSub = array_shift($v);
		}

		/**
		 * 检测默认项目
		 */
		else {
			if (! empty($default['alias']))
				$app = $default['alias'];

			if (isset($v[0])
				&& is_array($default['list'])
				&& in_array($v[0], $default['list'])
			)
				$appSub = array_shift($v);
		}

		/**
		 * 检测控制器和方法以及其它参数
		 */
		if (! empty($v)) {
			// $p = "/^[0-9a-zA-Z_]+$/";
			$data = array_slice($v, 0, 2);
			foreach ($data as $k => $item)
				$data[$k] = str_replace('.', '', $item);

			$len = count($v);
			for ($i = 2; $i < $len; $i += 2)
				$_GET[$v[$i]] = $v[$i + 1];
		}

		///
		return array(
			array(
				$app, $appSub
			), $data
		);
	}
}
